home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 364_01 / ifdef_ca.c < prev    next >
C/C++ Source or Header  |  1992-05-24  |  13KB  |  466 lines

  1. /*
  2. HEADER:         ;
  3. TITLE:          C-ACROSS;
  4. VERSION         1.02
  5.  
  6. DESCRIPTION:   "Utility for multiple module programs. Produces
  7.       Six indexes of functions, prototypes, and globals that
  8.       enable user to 'see across' modules for use in checking
  9.       and comparison.  One of these is type of hierarchical
  10.       functions list, a listing by module of functions
  11.       and calls made FROM them; another is alphabetical list
  12.       of functions and calls made TO them. Globals listed
  13.       in schematic descriptors which record all modifiers
  14.       and qualifiers and enable checking of declarators
  15.       across modules. Creates, on request, header file
  16.       consisting of prototypes constructed from function
  17.       definitions. Can list user types #defined and some
  18.       preprocessor #defines. Full documentation in README.CA";
  19.  
  20. KEYWORDS:       Utility, Cross Reference, Deubgging;
  21. SYSTEM:         MS-DOS;
  22. FILENAME:       IFDEF_CA.C;
  23.  
  24. WARNINGS:      "1. Assumes function definitions conform with
  25.         ANSI standards and have prototype form. See
  26.         also "Caveats and Restrictions" in README.CA.
  27.         2. Assumes syntactically correct source files.
  28.         3. Written and tested using Microsoft QuickC.
  29.         4. Copyright retained.  See Copyright
  30.         information in README.CA.";
  31.  
  32. SEE-ALSO:      EXIT_CA.C, FUNC_CA.C, GLOB_CA.C, IFDEF_CA.C, INTF_CA.C,
  33.            LINKL_CA.C, PARSE_CA.C, TDEF_CA.C, TYPES_CA, UTIL_CA.C,
  34.            UTLG_CA.C, XRF_CA.C, README.CA,
  35.            CA.H, CA.PRJ, CA.RPT, CDECL_CA.H, KEYWORDS.H;
  36. AUTHORS:       Myron Turner;
  37. COMPILERS:     Microsoft C;
  38.  
  39. */
  40.  
  41. /***************************  C-ACROSS  ***************************
  42.                    V. 1.02
  43.                Copyright (C) Myron Turner
  44.  
  45.               333 Bartlet Ave.
  46.               Winnipeg, Manitoba
  47.               Canada R3L 0Z9
  48.               (204) 284-8387
  49.  
  50. *********************************************************************/
  51.  
  52.  
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <string.h>
  56. #include <malloc.h>
  57.  
  58.  
  59. /* temporary storage of information on if/def defines for testing */
  60. /* & analysis of truth values in ifdef_true() */
  61. typedef struct if_def {
  62.     char *def1;              /* definition name */
  63.     char *def2;
  64.     unsigned int boolean1;   /* truth value of keyword [ifdef=1, ifndef=0 */
  65.     unsigned int boolean2;
  66.     int op;                 /*  relational operator in if/def expresion: */
  67.                 /*  either && or || */
  68. } IF_DEF;
  69.  
  70. /* stack of if/def defines & all undefs */
  71. typedef struct if_def_stackType {
  72.     char *def_name;
  73.     unsigned int def_status;   /* 0 = #undefined, 1 = #defined  */
  74.     struct if_def_stackType *next;
  75. } IF_DEF_STACK;
  76. IF_DEF_STACK *start_ifdef_stack = NULL;
  77.  
  78. #define EXIT_CODES
  79. #define IFDEFS_DEFINED
  80.  
  81. #include "ca.h"
  82. #include "ca_decl.h"
  83.  
  84.  
  85. #define EXCLUDE_IFDEF 1
  86. #define INCLUDE_IFDEF 0
  87. #define EXCLUDE_BLOCK -1
  88.  
  89. extern int verbose;
  90. #define increment_levels() if_level++; elif_level = else_level = if_level
  91.  
  92. #define _AND  1
  93. #define _OR   2
  94.  
  95. #define IFLEVEL_MAX  3
  96. #define DEFINE_TYPES 9
  97. enum DefineTYPES {  _DEFINED, _DEF, _IF,_ELSEIF, _ELSE,
  98.                _IFDEF, _IFNDEF, _UNDEF, _ENDIF };
  99.  
  100. int if_code[DEFINE_TYPES] = {    _DEFINED,  _DEF, _IF, _ELSEIF,
  101.                  _ELSE, _IFDEF, _IFNDEF,
  102.                  _UNDEF, _ENDIF };
  103.  
  104. char *elseif[DEFINE_TYPES] =  { "defined", "#define", "#if", "#elif",
  105.                 "#else", "#ifdef", "#ifndef",
  106.                 "#undef", "#endif"};
  107.  
  108. int is_else_if(char *p, int in_define)
  109. {
  110.   int def_type, found = 0, restore_str = 1;
  111.   char *new_line = p;
  112.  
  113.  /* This function begins by testing the token created in is_includeF() */
  114.  /* to see whether it is one of the #if/#def commands; we will */
  115.  /* restore the original string, if a newline character is not found, by */
  116.  /* replacing the '\0' inserted in the tokenizing function with a space. */
  117.  /* If a newline is not found the string hasn't been altered. */
  118.  
  119.  /* First find the null or newline */
  120.   while (*new_line != '\0' && *new_line != '\n') new_line++;
  121.   if (*new_line == '\n') {
  122.        *new_line = '\0';
  123.        restore_str = 0;
  124.        }
  125.  
  126.   for (def_type = _DEF; def_type <= _ENDIF; def_type++) {
  127.   if (found = test_token(p, elseif[def_type])) break;
  128.   }
  129.   if (found) {
  130.      if (restore_str)
  131.          *new_line = ' ';
  132.      if (if_code[def_type])
  133.       return(def_value(p, if_code[def_type]));
  134.        else
  135.        p = new_line++;
  136.      }
  137.  
  138.   return(in_define);
  139. }
  140.  
  141. static int def_value(char *p, int if_type)
  142. {
  143.   static int if_level = 0;
  144.   static int elif_level = 0;
  145.   static int else_level = 0;
  146.   static int if_status[IFLEVEL_MAX] = { 0, 0, 0 };
  147.   IF_DEF ifdefs;
  148.  
  149.      switch (if_type)
  150.      {
  151.      case _IF: case _IFDEF: case _IFNDEF:
  152.         if (if_level == IFLEVEL_MAX) break;
  153.         if (if_status[if_level])
  154.         if(if_status[if_level - 1] == EXCLUDE_IFDEF)
  155.         return(if_status[if_level] = EXCLUDE_BLOCK);
  156.      /* If_type converted in get_definition() to IFDEF or IFNDEF */
  157.         ifdefs = get_definition(p, if_type);
  158.         if (ifdefs.def1)
  159.           if(ifdef_true(ifdefs)) {
  160.           increment_levels();
  161.           return (if_status[if_level - 1] = INCLUDE_IFDEF);
  162.           }
  163.       increment_levels();
  164.       return (if_status[if_level - 1] = EXCLUDE_IFDEF);
  165.  
  166.  
  167.      case _ELSEIF:
  168.         if (elif_level != if_level) break;
  169.         elif_level--;  else_level--;
  170.         if (if_status[elif_level])
  171.         if(if_status[elif_level - 1] == EXCLUDE_BLOCK)
  172.           return (EXCLUDE_BLOCK);
  173.         if (if_status[elif_level] == INCLUDE_IFDEF)
  174.         return (EXCLUDE_IFDEF);
  175.      /* If_type converted in get_definition() to IFDEF or IFNDEF */
  176.         ifdefs = get_definition(p, if_type);
  177.         if (ifdefs.def1)
  178.           if(ifdef_true(ifdefs))
  179.           return (if_status[elif_level] = INCLUDE_IFDEF);
  180.  
  181.       return (if_status[elif_level] = EXCLUDE_IFDEF);
  182.  
  183.      case _ELSE:
  184.         if (else_level != if_level) break;
  185.         elif_level--;  else_level--;
  186.         if(if_status[else_level])
  187.         if(if_status[else_level - 1] == EXCLUDE_BLOCK)
  188.           return (EXCLUDE_BLOCK);
  189.         if (if_status[else_level] == INCLUDE_IFDEF)
  190.         return (EXCLUDE_IFDEF);
  191.         return (if_status[else_level] = INCLUDE_IFDEF);
  192.      case _ENDIF:
  193.         if_level--;
  194.         elif_level = else_level = if_level;
  195.         if_status[if_level] = INCLUDE_IFDEF;
  196.      break;
  197.  
  198.      case _DEF:
  199.        ifdefs = get_definition(p, if_type);
  200.        if (ifdefs.def1) push_ifdef(ifdefs.def1, 1);
  201.      break;
  202.  
  203.      case _UNDEF:
  204.        ifdefs = get_definition(p, if_type);
  205.        if (ifdefs.def1)
  206.           push_ifdef(ifdefs.def1, 0);
  207.      break;
  208.  
  209.      }
  210.  
  211.   return(if_status[if_level]);
  212.  
  213. }
  214.   /*                               0         1     2     3
  215. int if_code[DEFINE_TYPES] = {    _DEFINED,  _DEF, _IF, _ELSEIF,
  216.                    4      5        6
  217.                  _ELSE, _IFDEF, _IFNDEF,
  218.                     7      8
  219.                  _UNDEF, _ENDIF };
  220.     */
  221.  
  222. /* two preprocessor statements on one line not accepted: #else #if defined()*/
  223. static IF_DEF get_definition(char *p, int if_type)
  224. {
  225.   size_t strL = 0;
  226.   char *ptr  = elseif[if_type];
  227.   char *end_token, *boolean = NULL;
  228.   int boolean_found = 0, AND = 1, OR = 1;
  229.   IF_DEF ifdefs = { "", "", 0, 0, 0 };
  230.  
  231.   char temp[100], *temp_p = temp;
  232.   strcpy(temp, p);
  233.  
  234.   while (*ptr) {  ptr++; strL++; }
  235.   p += strL;
  236.   while (iswhite(*p)) p++;
  237.  
  238.   ifdefs.def1 = NULL;
  239.   ifdefs.def2 = NULL;
  240.   /* reject a second preprocessor statement on same line */
  241.   if (*p == '#') return (ifdefs);
  242.  
  243.   if (if_type == _IF || if_type == _ELSEIF) {
  244.   if ( *p == '!') {
  245.            p++;  ifdefs.boolean1 = 0;
  246.            }
  247.      else {
  248.      if_type = _IFNDEF;
  249.      ifdefs.boolean1 = 1;
  250.      }
  251.        }
  252.       else if (if_type == _IFDEF) ifdefs.boolean1 = 1;
  253.       else if (if_type == _IFNDEF) ifdefs.boolean1 = 0;
  254.  
  255.   while (iswhite(*p)) p++;
  256.  
  257.   ptr = NULL;
  258.  
  259.   p = isolate_token(p, &end_token);
  260.  
  261.   if (if_type == _DEF || if_type == _UNDEF) {
  262.        if (*(end_token - 1) != '\n') {
  263.       end_token++;
  264.       while (iswhite (*end_token)) end_token++;
  265.       if (*end_token != '\n') return(ifdefs);
  266.       }
  267.        *(end_token - 1) = '\0';
  268.        ifdefs.def1 = p;
  269.        return(ifdefs);
  270.        }
  271.  
  272.   if(*(end_token  - 1) == '\n')
  273.     *(--end_token) = '\0';
  274.   if (test_token(p, elseif[_DEFINED])) {
  275.     *end_token = ' ';  /*  replace null with space */
  276.  
  277.        do {
  278.  
  279.     boolean = NULL;
  280.     while (iswhite(*p)) p++;
  281.     if(boolean_found)
  282.        if (*p == '(')